#pragma once

namespace cr_debug
{
	template <bool> 
	struct StaticAssert 
	{

	};

	template <> 
	struct StaticAssert<true>
	{ 
		enum { static_assert_failed } ;
	};
}

#define CR_STATIC_ASSERT(c)		cr_debug::StaticAssert<(c)>::static_assert_failed

#if CR_ASSERTS_ENABLED

namespace cr_debug
{
	void Assert(const char* szCondition, const char* szFile, long line, const char* szMessage = 0, ...);
}

#define CR_HALT()								__debugbreak()

#define CR_ASSERT(c)							if (!(c)) { cr_debug::Assert(#c, __FILE__, __LINE__); CR_HALT(); }
#define CR_ASSERT_MSG(c, m)						if (!(c)) { cr_debug::Assert(#c, __FILE__, __LINE__, m); CR_HALT(); }
#define CR_ASSERT_MSG1(c, m, a1)				if (!(c)) { cr_debug::Assert(#c, __FILE__, __LINE__, m, a1); CR_HALT(); }
#define CR_ASSERT_MSG2(c, m, a1, a2)			if (!(c)) { cr_debug::Assert(#c, __FILE__, __LINE__, m, a1, a2); CR_HALT(); }
#define CR_ASSERT_MSG3(c, m, a1, a2, a3)		if (!(c)) { cr_debug::Assert(#c, __FILE__, __LINE__, m, a1, a2, a3); CR_HALT(); }
#define CR_ASSERT_MSG4(c, m, a1, a2, a3, a4)	if (!(c)) { cr_debug::Assert(#c, __FILE__, __LINE__, m, a1, a2, a3, a4); CR_HALT(); }

#else

#define CR_ASSERT(c)							
#define CR_ASSERT_MSG(c, m)						
#define CR_ASSERT_MSG1(c, m, a1)				
#define CR_ASSERT_MSG2(c, m, a1, a2)			
#define CR_ASSERT_MSG3(c, m, a1, a2, a3)		
#define CR_ASSERT_MSG4(c, m, a1, a2, a3, a4)	

#define CR_HALT()

#endif